<script setup>
import {ICONS} from "../const/index.js";
import {shallowRef} from "vue";
import {myInsert, myUpdate} from "../util/request.js";
import {isNotNull} from "../util/index.js";

/**
 * items 详细格式
 *
 * type: 表单项类型，支持 number, password, textarea, select, datetime, date, icon, cascader, text 9种，默认 text
 * label: 文案，默认表单项属性名
 * prop: 属性名
 * required: 是否必填，默认 false
 * disabled: 是否禁用，默认 false
 * readonly: 是否只读，默认 false
 * placeholder: 背景字，默认 "请输入.."
 * span: 每个表单项的宽度占24分之多少，默认 24，表示独占一行
 * hidden: 是否隐藏，默认 false，需要占位时改为 true
 * min: 最小值，默认 0，（type = number专属）
 * max: 最大值（type = number专属）
 * precision: 精度，默认 0（type = number专属）
 * rows: 行数，默认 8（type = textarea专属）
 * cols: 列数（type = textarea专属）
 * options: 下拉菜单项（type = select专属），格式 [{ label: '', value: '' }]
 * iconSize: 按钮大小，默认 14（type = icon专属）
 * options: 级联菜单项（type = cascader专属），格式 [{ label: '', value: '', children: [] }]
 * cascaderChange: 当级联菜单发生改变时触发的函数（不带小括号）
 */
let parent = defineProps({
  // 表单类型：支持 insert 和 update 两种
  type: {type: String, required: false, default: 'insert'},
  // 表单项：详细格式查看文档注释
  items: {type: Array, required: true},
  // 表单规则
  rules: {type: Object, required: true},
  // API函数：表单提交时调用的API函数（不带小括号）
  api: {type: Function, required: true},
  // API参数：API请求函数参数，作为请求参数
  params: {type: Object, required: true},
  // API参数：API请求函数参数，不作为请求参数，而是有一些其它作用
  args: {type: Object, required: false, default: null},
  // 回调函数：表单提交后调用的函数（不带小括号）
  callback: {type: Function, required: false},
  // 表单宽度
  width: {type: String, required: false, default: '100%'},
});

// 表单对象
let form = shallowRef();

// 添加数据: 发送请求 + 重置表单
async function insert() {
  await myInsert({
    form: form,
    api: parent['api'],
    params: parent['params'],
    args: parent['args'],
    callback: parent['callback'],
    successTip: true,
    successTipContent: '添加成功！'
  });
  form.value.resetFields;
}

// 修改数据: 发送请求 + 重置表单
async function update() {
  await myUpdate({
    form: form,
    api: parent['api'],
    params: parent['params'],
    args: parent['args'],
    callback: parent['callback'],
    successTip: true,
    successTipContent: '修改成功！'
  });
  form.value.resetFields;
}
</script>

<template>
  <el-form class="my-form"
           ref="form"
           status-icon
           label-width="auto"
           size="small"
           :model="params"
           :rules="rules"
           :style="{'width': width}">
    <el-row :gutter="20">
      <el-col class="layout-col"
              v-for="item in items"
              :key="item"
              :span="isNotNull(item['span']) ? item['span'] : 24">
        <el-form-item class="form-item"
                      :label="isNotNull(item['label']) ? item['label'] : item['prop']"
                      :prop="item['prop']"
                      :required="item['required']"
                      v-show="!item['hidden']">
          <!--数字框-->
          <el-input-number v-if="item['type'] === 'number'"
                           clearable
                           v-model="params[item['prop']]"
                           :min="isNotNull(item['min']) ? item['min'] : 0"
                           :max="item['max']"
                           :precision="isNotNull(item['precision']) ? item['precision'] : 0"
                           :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                           :disabled="item['disabled']"
                           :readonly="item['readonly']"/>
          <!--密码框-->
          <el-input v-else-if="item['type'] === 'password'"
                    clearable
                    show-password
                    v-model="params[item['prop']]"
                    :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                    :disabled="item['disabled']"
                    :readonly="item['readonly']"/>
          <!--文本域-->
          <el-input v-else-if="item['type'] === 'textarea'"
                    type="textarea"
                    clearable
                    resize="none"
                    v-model="params[item['prop']]"
                    :rows="isNotNull(item['rows']) ? item['rows'] : 8"
                    :cols="item['cols']"
                    :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                    :disabled="item['disabled']"
                    :readonly="item['readonly']"/>
          <!--下拉框-->
          <el-select v-else-if="item['type'] === 'select'"
                     clearable
                     filterable
                     v-model="params[item['prop']]"
                     :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                     :disabled="item['disabled']"
                     :readonly="item['readonly']">
            <el-option class="select-item"
                       v-for="option in item['options']"
                       :key="option"
                       :label="option['label']"
                       :value="option['value']"/>
          </el-select>
          <!--时间框-->
          <el-date-picker v-else-if="item['type'] === 'datetime'"
                          type="datetime"
                          clearable
                          v-model="params[item['prop']]"
                          format="YYYY-MM-DD HH:mm"
                          value-format="YYYY-MM-DDTHH:mm:ss"
                          :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                          :disabled="item['disabled']"
                          :readonly="item['readonly']"/>
          <!--日期框-->
          <el-date-picker v-else-if="item['type'] === 'date'"
                          type="date"
                          clearable
                          v-model="params[item['prop']]"
                          format="YYYY-MM-DD"
                          value-format="YYYY-MM-DD"
                          :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                          :disabled="item['disabled']"
                          :readonly="item['readonly']"/>
          <!--ICON单选框-->
          <el-radio-group v-else-if="item['type'] === 'icon'"
                          class="icon-list"
                          size="small"
                          v-model="params[item['prop']]">
            <el-radio-button class="icon-item"
                             v-for="icon in ICONS"
                             :key="icon"
                             :label="icon">
              <template #default>
                <el-icon :size="isNotNull(item['iconSize']) ? item['iconSize'] : 14">
                  <component :is="icon"/>
                </el-icon>
              </template>
            </el-radio-button>
          </el-radio-group>
          <!--级联框-->
          <el-cascader v-else-if="item['type'] === 'cascader'"
                       v-model="params[item['prop']]"
                       :options="item['options']"
                       :props="{expandTrigger: 'hover'}"
                       @change="params[item['cascaderChange']]"
                       style="width: 100%;"/>
          <!--文本框-->
          <el-input v-else
                    clearable
                    v-model="params[item['prop']]"
                    :placeholder="isNotNull(item['placeholder']) ? item['placeholder'] : '请输入..'"
                    :disabled="item['disabled']"
                    :readonly="item['readonly']"/>
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item class="btn-item">
      <el-button class="insert-btn"
                 v-if="type === 'insert'"
                 type="primary"
                 @click="insert">
        确认添加
      </el-button>
      <el-button class="update-btn"
                 v-else-if="type === 'update'"
                 type="primary"
                 @click="update">
        确认修改
      </el-button>
    </el-form-item>
  </el-form>
</template>

<style scoped lang="scss">
.my-form {
  .el-input-number, .el-button {
    width: 100%; // 宽度
  }
}

:deep(.el-date-editor) {
  --el-date-editor-width: 100%; // 宽度
}

.icon-list {
  margin-left: -2px; // 左外边距
  max-height: 160px; // 最大高度
  overflow-y: scroll; // Y滚动

  .el-radio-button {
    margin-bottom: 5px; // 下外边距
  }
}

/* 取消首尾按钮的圆角 */
:deep(.el-radio-button:first-child .el-radio-button__inner),
:deep(.el-radio-button:last-child .el-radio-button__inner) {
  border-radius: 0; // 圆角
}

/* 修改单选按钮样式 */
:deep(.el-radio-button--small .el-radio-button__inner) {
  border-left: 1px solid #7e7e7e; // 左边框
  margin: 0 2px; // 左右外边距
}
</style>